﻿/**************************************************************************
创建时间:	2015.5.8
作	  者:	张存
邮 	  箱:	zhangcunliang@126.com

描	述：sql建造器
记	录：
    2017.11.30  DbParam改到构造函数初始化
    2018.4.26   修改 AddSqlTextByGroup 的bug，当非参数话增加文本时会增加失败；
                增加 SQLTextLength 属性，可用于sqltext 的长度判断
                当合并SQL builder时的参数名重复问题处理 （2018.4.28 去掉该处理，因sql文与参数名对应，不可修改参数名）
    2018.6.6    增加可自定义参数名的增加参数方法
    2020.6.29   增加 AddSQLParam 方法，更方便拼接sql与参数值
                优化其它代码
    2021.2.1    增加sql文之后，由void改为 返回当前示例，用于链式编程
***************************************************************************/
using System;
using System.Collections.Generic;
using System.Text;

namespace ASmile.ORM.BuildSQLText
{
    public class ISqlBuilder : IDisposable
    {
        public static ISqlBuilder Create(string paramSignStr, string paramKey)
        {
            return new ISqlBuilder(paramSignStr, paramKey);
        }

        private ISqlBuilder(string paramSignStr, string paramKey)
        {
            ParamSignStr = paramSignStr;
            ParamKey = paramKey;
            SQL = new StringBuilder();
            DbParam = new Dictionary<string, object>();
        }

        int ParamCount { set; get; } = 0;

        string ParamSignStr { get; }

        string ParamKey { get; }

        StringBuilder SQL { get; }

        /// <summary>
        /// 返回sql文本
        /// </summary>
        public string SQLText
        {
            get
            {
                return SQL.ToString();
            }
        }
        /// <summary>
        /// 参数集合
        /// </summary>
        public Dictionary<string, object> DbParam { get; private set; }
        /// <summary>
        /// sql文本长度
        /// </summary>
        public int SQLTextLength
        {
            get { return SQL.Length; }
        }
        /// <summary>
        /// string.format()方式 追加sql文本
        /// </summary>
        public ISqlBuilder AddSQLText(string sql, params object[] args)
        {
            if (string.IsNullOrWhiteSpace(sql))
            {
                return this;
            }
            if (args == null || args.Length == 0)
            {
                SQL.Append(sql);
            }
            else
            {
                SQL.AppendFormat(sql, args);
            }
            return this;
        }
        /// <summary>
        /// 追加sql文本，支持string.format 方法，同时会把所有已有条件加上括号，并加上and符号
        /// </summary>
        public ISqlBuilder AddSqlTextByGroup(string sql, params object[] args)
        {
            if (sql == null && sql.Length < 2)
            {
                return this;
            }
            if (SQL.Length > 2)
            {
                SQL.Insert(0, "(");
                SQL.Append(")");
                SQL.Append(" and ");
                sql = "(" + sql + ")";
            }
            AddSQLText(sql, args);
            return this;
        }

        /// <summary>
        /// 追加sql文本，args 为参数值，同时会把所有已有条件加上括号，并加上and符号
        /// </summary>
        public ISqlBuilder AddSQLParamGroup(string sql, params object[] args)
        {
            if (sql == null && sql.Length < 2)
            {
                return this;
            }
            if (SQL.Length > 2)
            {
                SQL.Insert(0, "(");
                SQL.Append(")");
                SQL.Append(" and ");
                sql = "(" + sql + ")";
            }
            AddSQLParam(sql, args);
            return this;
        }
        /// <summary>
        /// 追加一个参数
        /// </summary>
        public string AddParam(object dbParam)
        {
            string paramName = string.Format("{0}{1}{2}", ParamSignStr, ParamKey, ParamCount);
            if (dbParam == null) dbParam = DBNull.Value;
            DbParam.Add(paramName, dbParam);
            ParamCount++;
            return paramName;
        }
        /// <summary>
        /// 根据参数名增加参数，参数名存在返回false，但仍会设置该参数值
        /// </summary>
        /// <param name="paramName">参数名</param>
        /// <param name="dbParam">参数对象</param>
        /// <returns>参数列表存在返回false，不存在返回true</returns>
        public bool AddParam(string paramName, object dbParam)
        {
            if (dbParam == null) dbParam = DBNull.Value;
            paramName = string.Format("{0}{1}", ParamSignStr, paramName);
            if (DbParam.ContainsKey(paramName))
            {
                DbParam[paramName] = dbParam;
                return false;
            }
            else
            {
                DbParam.Add(paramName, dbParam);
                return true;
            }
        }
        /// <summary>
        /// 追加sql文本与参数, param为参数对象值
        /// </summary>
        public ISqlBuilder AddSQLParam(string sql, params object[] param)
        {
            if (string.IsNullOrWhiteSpace(sql))
            {
                return this;
            }
            string[] paramName = new string[param.Length];
            for (int i = 0; i < param.Length; i++)
            {
                paramName[i] = AddParam(param[i]);
            }
            string newSql = string.Format(sql, paramName);
            SQL.Append(newSql);
            return this;
        }
        /// <summary>
        /// 清除sql脚本和参数
        /// </summary>
        public void ClearResult()
        {
            ClearSQL();
            if (DbParam != null) DbParam.Clear();
            ParamCount = 0;
        }
        /// <summary>
        /// 只清除sql脚本
        /// </summary>
        public void ClearSQL()
        {
            SQL.Clear();
        }

        public void Dispose()
        {
            ClearResult();
        }

        public void AppendDbParam(Dictionary<string, object> dbParam)
        {
            if (DbParam == null)
            {
                DbParam = new Dictionary<string, object>();
            }
            if (dbParam != null)
            {
                foreach (var item in dbParam.Keys)
                {
                    DbParam.Add(item, dbParam[item]);
                }
            }
        }
    }
}